<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        .cont{position: relative;margin: 0 20px;}
        .m_box{width:300px;height:300px;}
        .m_box img{width:300px;height:300px;}
        .m_box span{position: absolute;left:0;top:0;background: rgba(255,0,0,0.6);display:none;}

        .b_box{width:300px;height:300px;overflow: hidden;position: absolute;display:none;left: 340px;top:0;}
        .b_box img{width:1000px;height:1000px;position: absolute;left:0;top:0;}

        .list{margin: 20px 0;background: #ccc;width:300px;display:flex;align-items: center;}
        .list img{margin: 0 6px;}
    </style>
</head>
<body>
    <div class="cont">
        <div class="m_box">
            <img src="./imgs/m0.jpg" alt="">
            <span></span>
        </div>
        <div class="b_box">
            <img src="./imgs/l0.jpg" alt="">
        </div>
        <div class="list"></div>
    </div>
</body>
<script>
    
    function SmallToBig(){
        this.mBox = document.querySelector(".m_box");
        this.mImg = document.querySelector(".m_box img");
        this.span = document.querySelector(".m_box span");
        this.bBox = document.querySelector(".b_box");
        this.bImg = document.querySelector(".b_box img");
        this.cont = document.querySelector(".cont");
        this.list = document.querySelector(".list");

        // 1. 获取数据
        this.imgData = [{
            small: "./imgs/s0.jpg",
            middle: "./imgs/m0.jpg",
            large: "./imgs/l0.jpg"
        },{
            small: "./imgs/s1.jpg",
            middle: "./imgs/m1.jpg",
            large: "./imgs/l1.jpg"
        },{
            small: "./imgs/s2.jpg",
            middle: "./imgs/m2.jpg",
            large: "./imgs/l2.jpg"
        }];

        // 2. 根据数据渲染页面
        this.createList();

        this.addEvent();
    }
    SmallToBig.prototype.createList = function(){
        // 根据数据渲染页面
        let str = "";
        this.imgData.forEach(val=>{
            str += `<img src="${val.small}" />`;
        })
        this.list.innerHTML = str;
        // 绑定列表中图片的事件，点击切换图片
        this.changeImg()
    }

    SmallToBig.prototype.changeImg = function(){
        const that = this;
        for(let i=0;i<this.list.children.length;i++){
            this.list.children[i].index = i;
            this.list.children[i].onclick = function(){
                that.mImg.src = (that.imgData[this.index].middle);
                that.bImg.src = (that.imgData[this.index].large);
            }
        }
    }

    SmallToBig.prototype.addEvent = function(){
        const that = this;
        this.mBox.onmouseover = function(){
            that.show();
        }
        this.mBox.onmouseout = function(){
            that.hide();
        }
        this.mBox.onmousemove = function(){
            that.move();
        }
    }
    SmallToBig.prototype.show = function(){
        this.span.style.display = "block";
        this.bBox.style.display = "block";
        const x = this.bBox.offsetWidth / this.bImg.offsetWidth;
        const y = this.bBox.offsetHeight / this.bImg.offsetHeight;
        this.span.style.width = this.mBox.offsetWidth * x + "px";
        this.span.style.height = this.mBox.offsetHeight * y + "px";
    }
    SmallToBig.prototype.hide = function(){
        this.span.style.display = "none";
        this.bBox.style.display = "none";
    }
    SmallToBig.prototype.move = function(eve){
        const e = eve || window.event;
        let l = e.clientX - this.span.offsetWidth/2 - this.mBox.offsetLeft - this.cont.offsetLeft;
        let t = e.clientY - this.span.offsetHeight/2 - this.mBox.offsetTop - this.cont.offsetTop;
        if(l<0) l=0;
        if(t<0) t=0;
        if(l>this.mBox.offsetWidth-this.span.offsetWidth){
            l=this.mBox.offsetWidth-this.span.offsetWidth
        }
        if(t>this.mBox.offsetHeight-this.span.offsetHeight){
            t=this.mBox.offsetHeight-this.span.offsetHeight
        }
        this.span.style.left = l + "px";
        this.span.style.top = t + "px";
        const x = l / (this.mBox.offsetWidth-this.span.offsetWidth);
        const y = t / (this.mBox.offsetHeight-this.span.offsetHeight);
        this.bImg.style.left = x * (this.bBox.offsetWidth - this.bImg.offsetWidth) + "px";
        this.bImg.style.top = y * (this.bBox.offsetHeight - this.bImg.offsetHeight) + "px";
    }
    new SmallToBig();

</script>
</html>